﻿/*********************************************************************************
**                                                                              **
**  Copyright (C) 2022-2022 LiLong                                              **
**  This file is part of BluetoothCpp.                                          **
**                                                                              **
**  BluetoothCpp is free software: you can redistribute it and/or modify        **
**  it under the terms of the GNU Lesser General Public License as published by **
**  the Free Software Foundation, either version 3 of the License, or           **
**  (at your option) any later version.                                         **
**                                                                              **
**  BluetoothCpp is distributed in the hope that it will be useful,             **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of              **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               **
**  GNU Lesser General Public License for more details.                         **
**                                                                              **
**  You should have received a copy of the GNU Lesser General Public License    **
**  along with BluetoothCpp.  If not, see <https://www.gnu.org/licenses/>.      **
**********************************************************************************/
#include "Server.h"
#include "Socket.h"
#ifdef WIN32
#include "Private/ServerWin.h"
#endif

#include <thread>

namespace BTH
{
struct Server::Impl
{
#ifdef WIN32
    ServerWin server;
#endif
    std::jthread thread;
};

Server::Server() : m_impl(std::make_unique<Impl>()) {}

Server::~Server() {}

void Server::listen(const std::function<void(std::shared_ptr<Socket>)>& callback, const Uuid& uuid /*= {}*/)
{
    m_impl->server.listen(uuid);
    m_impl->thread = std::jthread(
        [this, callback](const std::stop_token& st)
        {
            while (!st.stop_requested())
            {
                auto h = m_impl->server.accept();
                std::invoke(callback, std::shared_ptr<Socket>(new Socket(h)));
            }
        });
}

void Server::close()
{
    if (m_impl->thread.joinable())
    {
        m_impl->thread.request_stop();
        m_impl->thread.join();
    }
    m_impl->server.close();
}

Handle Server::handle() const { return m_impl->server.handle(); }

} // namespace BTH
